/**
 * @project sky-take-out_1
 * @author MECHREVO
 * @date 2023/12/12 09:26:38
 * @version 1.0
 */
package com.sky.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersPageQueryDTO;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.Orderservice;
import com.sky.service.ShoppingCartService;
import com.sky.vo.*;
import com.sky.webScoket.WebSocketServer;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;





@Service
public class OrderserviceImpl implements Orderservice {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private AddressMapper addressMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderAdminMapper orderAdminMapper;
    @Autowired
    private ShoppingCartService shoppingCartService;
    @Autowired
    private WebSocketServer webSocketServer;
    @Autowired
    private  UserMapper userMapper;
    @Override
    public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {
        AddressBook addressBook = addressMapper.selectById(ordersSubmitDTO.getAddressBookId());
        if(Objects.isNull(addressBook)){
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        //核心代码
        //查询购物车详情
        ShoppingCart shoppingCartQuery = new ShoppingCart();
        shoppingCartQuery.setUserId(BaseContext.getCurrentId());
        List<ShoppingCart> selectlist = shoppingCartMapper.selectlist(shoppingCartQuery);
        if(selectlist ==null ||selectlist.isEmpty()){
            throw new AddressBookBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }
        //生成订单号 -主键返回
        Orders orders = new Orders();
        long currentTimeMillis = System.currentTimeMillis();
        orders.setNumber(String.valueOf(currentTimeMillis));
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setUserId(BaseContext.getCurrentId());
        orders.setAddressBookId(ordersSubmitDTO.getAddressBookId());
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayMethod(1);
        orders.setPayStatus(Orders.UN_PAID);
        //普通
      /*  BigDecimal bigDecimal = new BigDecimal(0);
        for (ShoppingCart shoppingCart : selectlist) {
            shoppingCart.getAmount().multiply(new BigDecimal(shoppingCart.getNumber()));
            bigDecimal= bigDecimal.add(shoppingCart.getAmount());
        }*/
        BigDecimal bigDecimal = new BigDecimal("0");
        bigDecimal= bigDecimal.add(new BigDecimal(6));
        bigDecimal= bigDecimal.add(new BigDecimal(ordersSubmitDTO.getPackAmount()));
        BigDecimal reduce = selectlist.stream()
                .map(shoppingCart -> shoppingCart.getAmount().multiply(new BigDecimal(shoppingCart.getNumber())))
                .reduce(bigDecimal, BigDecimal::add);//(a,b)->a.add(b)
        orders.setAmount(reduce);
        orders.setRemark(ordersSubmitDTO.getRemark());
        orders.setUserName(addressBook.getConsignee());
        orders.setPhone(addressBook.getPhone());
        String address=addressBook.getProvinceName()+addressBook.getCityName()+addressBook.getDistrictName()+addressBook.getDetail();
        orders.setAddress(address);
        orders.setConsignee(addressBook.getConsignee());
        orders.setEstimatedDeliveryTime(ordersSubmitDTO.getEstimatedDeliveryTime());
        orders.setDeliveryStatus(ordersSubmitDTO.getDeliveryStatus());
        orders.setDeliveryTime(LocalDateTime.now());
        orders.setPackAmount(ordersSubmitDTO.getPackAmount());
        orders.setTablewareNumber(ordersSubmitDTO.getTablewareNumber());
        orders.setTablewareStatus(ordersSubmitDTO.getTablewareStatus());
        orderMapper.insert(orders);
        //订单生成

        List<OrderDetail> collect = selectlist.stream()
                .map(shoppingCart -> {
                    OrderDetail orderDetail = new OrderDetail();

                    BeanUtils.copyProperties(shoppingCart, orderDetail);
                    orderDetail.setOrderId(orders.getId());
                    return orderDetail;
                }).collect(Collectors.toList());
        orderDetailMapper.insert(collect);
        OrderSubmitVO orderSubmitVO = new OrderSubmitVO();
        orderSubmitVO.setId(orders.getId());
        orderSubmitVO.setOrderNumber(orders.getNumber());
        orderSubmitVO.setOrderAmount(orders.getAmount());
        orderSubmitVO.setOrderTime(orders.getOrderTime());
        shoppingCartMapper.deleteById(shoppingCartQuery);
        return orderSubmitVO;
    }

    @Override
    public void paySuccess(String number) {
        Orders ordersQuery = new Orders();
        ordersQuery.setNumber(number);
        Orders orders=orderMapper.selectOne(ordersQuery);
        orders.setStatus(Orders.TO_BE_CONFIRMED);
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setPayStatus(Orders.PAID);
        orderMapper.updateById(orders);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type",1);
        jsonObject.put("orderId",orders.getId());
        jsonObject.put("content",orders.getNumber());
        webSocketServer.sendToAllClient(jsonObject.toJSONString());
    }

    @Override
    public PageResult<?> selectOrders(OrdersPageQueryDTO ordersPageQueryDTO) {
        PageHelper.startPage(ordersPageQueryDTO.getPage(),ordersPageQueryDTO.getPageSize());
        List<Orders> orders=orderMapper.selectOrders(ordersPageQueryDTO);
        List<OrderVO> orderVOList=new ArrayList<>();
        for (Orders order : orders) {
            OrderVO orderVO = new OrderVO();
            List<OrderDetail> list=orderMapper.selectOnedetail(order);
            orderVO.setOrderDetailList(list);
            BeanUtils.copyProperties(order,orderVO);
            orderVOList.add(orderVO);
        }
        Page<Orders> p=(Page<Orders>) orders;
        PageResult<?> pageResult = new PageResult(p.getTotal(), orderVOList);
        return pageResult;
    }

    @Override
    public OrderVO selectOrderDetailByOrderId(Long id) {
        Orders orders=orderAdminMapper.selectOrderByOrderId(id);
        OrderVO orderVO = new OrderVO();
        List<OrderDetail> orderDetail= orderAdminMapper.selectOrderDetailByOrderId(orders);
        orderVO.setOrderDetailList(orderDetail);
        BeanUtils.copyProperties(orders,orderVO);
        StringBuilder stringBuilder = new StringBuilder();
        for (OrderDetail detail : orderDetail) {
            stringBuilder.append(detail.getName()).append(" ");
        }
        orderVO.setOrderDishes(stringBuilder.toString());
        return orderVO;

    }

    @Override
    public void cancel(Long id) {
        Orders orders=orderMapper.selectById(id);
        if(orders.getStatus()>=Orders.TO_BE_CONFIRMED){
            orders.setStatus(Orders.REFUND);
        }
        orderMapper.updatecancel(orders);
    }

    @Override
    @Transactional
    public void repetition(Long id) {
        /*Orders orders = orderMapper.selectById(id);
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setOrderTime(LocalDateTime.now());
        orderMapper.insert(orders);
        List<OrderDetail> collect=orderDetailMapper.selectById(id);
        for (OrderDetail orderDetail : collect) {
            orderDetail.setOrderId(orders.getId());
        }
        orderDetailMapper.insert(collect);
        System.out.println("3242342");*/
        Orders orders = orderMapper.selectById(id);
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setOrderTime(LocalDateTime.now());
        List<OrderDetail> collect=orderDetailMapper.selectById(id);
        List<ShoppingCart> shoppingCarts = collect.stream().map(collects -> {
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(collects, shoppingCart);
            shoppingCart.setUserId(BaseContext.getCurrentId());
            shoppingCart.setCreateTime(LocalDateTime.now());
            return shoppingCart;
        }).collect(Collectors.toList());
        shoppingCartService.clean();
        shoppingCartMapper.insertshoppingCart(shoppingCarts);
    }

    @Override
    public void reminder(Long id) {
        Orders orders = orderMapper.selectById(id);
        if(Objects.isNull(orders)){
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type",2);
        jsonObject.put("orderId",orders.getId());
        jsonObject.put("content",orders.getNumber());
        webSocketServer.sendToAllClient(jsonObject.toJSONString());
    }

    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        List<Map<String, Object>> maplist = orderAdminMapper.selectturnoverStatistics(begin,end);
        String dateList = maplist.stream()
                .map(item -> (String) item.get("day"))
                .collect(Collectors.joining(", "));

        String turnover = maplist.stream().map(item -> (BigDecimal) item.get("turnover"))
                .map(BigDecimal::toString)
                .collect(Collectors.joining(", "));
        TurnoverReportVO turnoverReportVO =new TurnoverReportVO();
        turnoverReportVO.setDateList(dateList);
        turnoverReportVO.setTurnoverList(turnover);
        return turnoverReportVO;
    }

    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        //时间列表的问题
        ArrayList<LocalDate> localDates = new ArrayList<>();
        localDates.add(begin);
        while (true){
            begin=begin.plusDays(1);
            if(begin.isAfter(end)){
                break;
            }
            localDates.add(begin);
        }
        //把时间列表作为参数 进行sql语句查询
        List<Map<String ,Object> >mapList=userMapper.selectuserStatistics(localDates);
        //数据处理
        String dateList = mapList.stream()
                .map(item -> (String) item.get("day"))
                .collect(Collectors.joining(", "));
        String TotalUserList = mapList.stream().map(item -> (Long) item.get("all_count"))
               /* .map(Object::toString)*/
                .map(String::valueOf)
                .collect(Collectors.joining(", "));

        String NewUserList = mapList.stream().map(item -> (Long) item.get("user_count"))
               /* .map(Object::toString)*/
                .map(String::valueOf)
                .collect(Collectors.joining(", "));
        //结果封装
        UserReportVO userReportVO = new UserReportVO();
        userReportVO.setDateList(dateList);
        userReportVO.setTotalUserList(TotalUserList);
        userReportVO.setNewUserList(NewUserList);
        return userReportVO;
    }

    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        Map<String,Object>map=orderMapper.selectordersStatistics(begin ,end);
        ArrayList<LocalDate> localDates = new ArrayList<>();
        localDates.add(begin);
        while (true){
            begin=begin.plusDays(1);
            if(begin.isAfter(end)){
                break;
            }
            localDates.add(begin);
        }
        List<Map<String,Object>>mapList=orderMapper.selectordersStatistics2(localDates);
        //数据处理
        String DateList = mapList.stream()
                .map(item -> (String) item.get("day"))
                .collect(Collectors.joining(", "));
        String OrderCountList = mapList.stream().map(item -> (Long) item.get("total_number"))
                /* .map(Object::toString)*/
                .map(String::valueOf)
                .collect(Collectors.joining(", "));

        String ValidOrderCountList = mapList.stream().map(item -> (Long) item.get("number_valid_orders"))
                /* .map(Object::toString)*/
                .map(String::valueOf)
                .collect(Collectors.joining(", "));
        Long totalNumber = (Long) map.get("total_number");
        Long numberValidOrders = (Long) map.get("number_valid_orders");
        BigDecimal orderCompletionRate = (BigDecimal) map.get("order_completion_rate");
        OrderReportVO orderReportVO = new OrderReportVO();
        orderReportVO.setDateList(DateList);
        orderReportVO.setOrderCountList(OrderCountList);
        orderReportVO.setValidOrderCountList(ValidOrderCountList);
        orderReportVO.setTotalOrderCount(totalNumber.intValue());
        orderReportVO.setValidOrderCount(numberValidOrders.intValue());
        orderReportVO.setOrderCompletionRate(orderCompletionRate.doubleValue());

        return orderReportVO;
    }

    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
            List<Map<String,Object>>mapList=orderMapper.top10(begin,end);
        String nameList = mapList.stream()
                .map(item -> (String) item.get("name"))
                .collect(Collectors.joining(", "));
        String numberList = mapList.stream()
                .map(item -> (Long) item.get("count"))
                .map(String::valueOf)
                .collect(Collectors.joining(", "));
        SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
        salesTop10ReportVO.setNameList(nameList);
        salesTop10ReportVO.setNumberList(numberList);

        return salesTop10ReportVO;
    }
}
